package Client;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.net.*;
import java.util.ArrayList;
import java.io.*;

import javax.imageio.ImageIO;
import javax.swing.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

// Client class to let a user play Tic-Tac-Toe with
// another user across a network.
public class TileHandler extends JPanel {

	// weird and random xml variable initializers
	public int tileLength = -1;
	public int spriteWidth = -1;
	public int spriteHeight = -1;
	public int tileWidth = 64;
	public int tileHeight = 64;
	public int spacing = 0;
	public int margin = 0;
	public int windowWidth = 900;
	public int windowHeight = 700;
	Element frstTileset, frstImage;
	String spriteSource;
	String data = "";
	ArrayList<String> tiles;
	String[][] tileCoordinates;
	BufferedImage tileSet = null;
	EaTGClient parent = null;
	boolean wait = true;
	int tilesCount = 0;
	ArrayList<BufferedImage> tilesPaint = new ArrayList<BufferedImage>();
	ArrayList<Point> tilePoints = new ArrayList<Point>();
	public GribonnsAPI a = new GribonnsAPI();
	public Point mapStart = new Point(0, 0);

	public TileHandler() {
	}

	public TileHandler(EaTGClient main) {
		parent = main;
	}

	public class SplashGUI extends javax.swing.JFrame {

		/** Creates new form GEGrabberGUITest */
		public SplashGUI() {
			initComponents();
		}

		/**
		 * This method is called from within the constructor to initialize the
		 * form. WARNING: Do NOT modify this code. The content of this method is
		 * always regenerated by the Form Editor.
		 */
		@SuppressWarnings("unchecked")
		// <editor-fold defaultstate="collapsed" desc="Generated Code">
		private void initComponents() {
			jLabel1 = new javax.swing.JLabel();
			jProgressBar2 = new javax.swing.JProgressBar();
			jProgressBar3 = new javax.swing.JProgressBar();
			jLabel2 = new javax.swing.JLabel();

			setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
			setTitle("Splash");

			jLabel1.setLabelFor(jProgressBar2);
			jLabel1.setText("Total progress: ");

			jLabel2.setLabelFor(jProgressBar2);
			jLabel2.setText("Current progress: ");

			javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
					getContentPane());
			getContentPane().setLayout(layout);
			layout.setHorizontalGroup(layout
					.createParallelGroup(
							javax.swing.GroupLayout.Alignment.LEADING)
					.addComponent(jLabel1)
					.addComponent(jProgressBar2,
							javax.swing.GroupLayout.PREFERRED_SIZE,
							javax.swing.GroupLayout.DEFAULT_SIZE,
							javax.swing.GroupLayout.PREFERRED_SIZE)
					.addComponent(jLabel2)
					.addComponent(jProgressBar3,
							javax.swing.GroupLayout.PREFERRED_SIZE,
							javax.swing.GroupLayout.DEFAULT_SIZE,
							javax.swing.GroupLayout.PREFERRED_SIZE));
			layout.setVerticalGroup(layout
					.createParallelGroup(
							javax.swing.GroupLayout.Alignment.LEADING)
					.addGroup(
							layout.createSequentialGroup()
									.addComponent(
											jProgressBar2,
											javax.swing.GroupLayout.PREFERRED_SIZE,
											javax.swing.GroupLayout.DEFAULT_SIZE,
											javax.swing.GroupLayout.PREFERRED_SIZE)
									.addGap(0, 0, 0)
									.addComponent(jLabel1)
									.addPreferredGap(
											javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
									.addComponent(
											jProgressBar3,
											javax.swing.GroupLayout.PREFERRED_SIZE,
											javax.swing.GroupLayout.DEFAULT_SIZE,
											javax.swing.GroupLayout.PREFERRED_SIZE)
									.addGap(0, 0, 0)
									.addComponent(jLabel2)
									.addContainerGap(
											javax.swing.GroupLayout.DEFAULT_SIZE,
											Short.MAX_VALUE)));

			pack();
		}// </editor-fold>

		public void changeTotal(String text, int percent) {
			jLabel1.setText("Total progress: " + text);
			jProgressBar2.setValue(percent);
		}

		public void changeCur(String text, int percent) {
			jLabel2.setText((!text.isEmpty() ? "Current progress: " : "")
					+ text);
			jProgressBar3.setValue(percent);
		}

		// Variables declaration - do not modify
		private javax.swing.JLabel jLabel1;
		private javax.swing.JLabel jLabel2;
		private javax.swing.JProgressBar jProgressBar2;
		private javax.swing.JProgressBar jProgressBar3;
		// End of variables declaration
	}

	public void LoadXMLMap() {
		try {
			// System.out.println("my location is " +
			// getClass().getProtectionDomain().getCodeSource().getLocation());
			SplashGUI sg = new SplashGUI();
			sg.setSize(300, 115);
			sg.setResizable(false);
			sg.setVisible(true);
			sg.changeTotal("Loading map file", 0);
			sg.changeCur("Loading map file", 0);

			// File file = new File(baseurl + "Maps/thegame.tmx");

			sg.changeTotal("Parsing map file", 10);
			System.out.println("Load completed. Parsing map");
			sg.changeCur("Parsing attributes", 0);
			// System.out.println("width: " +
			// doc.getDocumentElement().getAttribute("width"));

			tiles = new ArrayList<String>();

			for (String s : data.split(",")) {
				tiles.add(s);
			}
			tileCoordinates = new String[spriteWidth][spriteHeight];

			for (int tileX = 0; tileX < spriteWidth; tileX++) {
				for (int tileY = 0; tileY < spriteHeight; tileY++) {
					tileCoordinates[tileX][tileY] = tiles
							.get((tileX + (tileY * spriteWidth)));
					sg.changeCur(
							"Adding tiles",
							Math.round((tileX + (tileY * spriteWidth))
									/ tiles.size() * 100));
				}
			}

			sg.changeTotal("Loading tileset", 50);
			sg.changeCur("Loading tileset image", 30);
			System.out.println("Parse completed. Loading tileset");
			String filePath = getClass().getProtectionDomain().getCodeSource()
					.getLocation().getPath()
					+ "Maps/".replace("%20", " ");
			String tilesetLocation = "file://" + filePath + "Tiles.png";

			try {
				tileSet = null;
				final URL agi = new URL(tilesetLocation);
				tileSet = ImageIO.read(agi);
			} catch (Exception e) {
				System.out.println("Error while parsing " + tilesetLocation);
				e.printStackTrace();
			}
			System.out.println("Tileset loaded. " + tilesetLocation);
			new Thread(new getMap()).start();
			sg.changeTotal("Loading tileset", 50);
			sg.changeCur("Calculating map", 80);
			wait = true;
			while (wait) {
				Thread.sleep(500);
			}
			sg.changeTotal("Done", 100);
			sg.changeCur("", 100);
			Thread.sleep(500);
			sg.dispose();

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	public class getMap implements Runnable {

		public int offsetX = 0;
		public int offsetY = 0;

		public void run() {
			int startUpX = 0;
			int startUpY = 0;

			if (offsetX > 0) {
				startUpX = Math.round(offsetX / tileWidth);
			}
			if (offsetY > 0) {
				startUpY = Math.round(offsetY / tileHeight);
			}
			int spacingerX = 0;

			for (int spriteForX = startUpX; spriteForX < spriteWidth; spriteForX++) {
				if (spriteForX > windowWidth) {
					continue;
				}
				int spacingerY = 0;
				for (int spriteForY = startUpY; spriteForY < spriteHeight; spriteForY++) {
					if (spriteForY > windowHeight) {
						continue;
					}
					int tileNum = Integer
							.parseInt(tileCoordinates[spriteForX][spriteForY]);

					if (tileNum <= 0) {
						continue;
					}
					int destY = (spriteForY - startUpY) * tileWidth
							- spacingerY;
					int destX = (spriteForX - startUpX) * tileWidth
							- spacingerX;
					int tilesPerRow = Math
							.round(tileSet.getWidth() / tileWidth);

					int sourceX = (tileNum - 1) % tilesPerRow;
					int sourceY = (tileNum - 1) / tilesPerRow;

					int tmpSrcX = sourceX * margin;
					int tmpSrcY = sourceY * margin;

					sourceX *= tileWidth;
					sourceY *= tileHeight;

					sourceX += tmpSrcX;
					sourceY += tmpSrcY;

					BufferedImage tempTile = new BufferedImage(tileWidth
							- spacing * 2, tileHeight - spacing * 2, 1);

					for (int startX = 0; startX < tileWidth - spacing; startX++) {
						for (int startY = 0; startY < tileHeight - spacing; startY++) {
							if ((startX < 0) || (startY < 0) || (sourceX < 0)
									|| (sourceY < 0)) {
								continue;
							}
							int x = sourceX + startX;
							int y = sourceY + startY;
							try {
								int oRGB = tileSet.getRGB(x, y);
								tempTile.setRGB(startX - spacing, startY
										- spacing, oRGB);
							} catch (Exception e) {
							}
						}
					}
					tilesCount++;
					tilesPaint.add(tempTile);
					tilePoints.add(new Point(destX, destY));

					spacingerY += spacing * 2;
				}
				spacingerX += spacing * 2;
			}
			wait = false;
		}
	}

	public int offsetX = 0;
	public int offsetY = 0;

	@Override
	public void paint(Graphics g) {
		Point me = parent.me.getScreenLoc();
		int x = 0;
		int y = 0;
		if (me.x < (windowWidth / 2)) {
			parent.boo.movePlayerX = false;
			x = 0;
		} else {
			x = -(me.x - (windowWidth/ 2));
			parent.boo.movePlayerX = true;
		}
		if (me.y < (windowHeight / 2)) {
			parent.boo.movePlayerY = false;
			y = 0;
		} else {
			y = -(me.y - (windowHeight / 2));
			parent.boo.movePlayerY = true;
		}		
		int x2 = 0;
		int y2 = 0;
		if (me.x < (windowWidth / 2)) {
			x2 = 0;
		} else {
			x2 = -(me.x - (windowWidth / 2));
		}
		if (me.y < (windowHeight / 2)) {
			y2 = 0;
		} else {
			y2 = -(me.y - (windowHeight / 2));
		}
		mapStart = new Point(x2, y2);
		for (int i = 0; i < tilesCount; i++) {
			Point p = tilePoints.get(i);
			drawTile(g, tilesPaint.get(i), p, me, x, y);
		}

	}

	public void drawTile(Graphics g, BufferedImage tile, Point p, Point me,
			int x, int y) {
		if (p.x <= (windowWidth + me.x) && p.y < (windowHeight + me.y)
				&& p.x >= (me.x - (windowWidth / 2) - tileWidth)
				&& p.y >= (me.y - (windowHeight / 2) - tileHeight)) {
			x += p.x;
			y += p.y;
			/*if (xCenter)
				x = windowWidth /2;
			if (yCenter)
				y = windowHeight /2;*/
			g.drawImage(tile, x, y, null);
		}
	}
}